const {src, dest, series, parallel, watch} = require('gulp');
const loadPlugins = require('gulp-load-plugins');
const plugins = loadPlugins();

const del = require('del');
const browserSync = require('browser-sync');
const bs = browserSync.create();

const fs = require('fs');
const path = require('path');

let config = {
    build: {
        src: 'src',
        public: 'public',
        dist: 'dist',
        temp: 'temp',
        paths: {
            style: 'assets/styles/*.scss',
            script: 'assets/scripts/*.js',
            pages: '*.html',
            images: 'assets/images/**',
            fonts: 'assets/fonts/**'
        }
    }
};

let configFile = path.join(process.cwd(), 'pages.config.js');
if (fs.existsSync(configFile)) {
    let customConfig = require(configFile);
    config = Object.assign(config, customConfig);
}

const style = () => {
    return src(config.build.paths.style, {base: config.build.src, cwd: config.build.src})
        .pipe(plugins.sass({outputStyle: 'expanded'}))
        .pipe(dest(config.build.temp));
}

const script = () => {
    return src(config.build.paths.script, {base: config.build.src, cwd: config.build.src})
    .pipe(plugins.babel({presets: [require('@babel/preset-env')]}))
    .pipe(dest(config.build.temp));
}

const pages = () => {
    return src(config.build.paths.pages, {base: config.build.src, cwd: config.build.src})
    .pipe(plugins.swig({data: config.data}))
    .pipe(dest(config.build.temp));
}

const images = () => {
    return src(config.build.paths.images, {base: config.build.src, cwd: config.build.src})
    .pipe(plugins.imagemin())
    .pipe(dest(config.build.dist));
}

const fonts = () => {
    return src(config.build.paths.fonts, {base: config.build.src, cwd: config.build.src})
    .pipe(plugins.imagemin())
    .pipe(dest(config.build.dist));
}

const extra = () => {
    return src('**', {base: config.build.public, cwd: config.build.public})
    .pipe(dest(config.build.dist));
}

const clean = () => {
    return del([config.build.temp, config.build.dist]);
}

const useref = () => {
    return src(config.build.paths.pages, {base: config.build.temp, cwd: config.build.temp})
    .pipe(plugins.useref({searchPath: [config.build.temp, '.']}))
    .pipe(plugins.if(/.js$/, plugins.uglify()))
    .pipe(plugins.if(/.css$/, plugins.cleanCss()))
    .pipe(plugins.if(/.html$/, plugins.htmlmin({
        collapseWhitespace: true,
        minifyCSS: true,
        minifyJS: true
    })))
    .pipe(dest(config.build.dist));
}

const serve = () => {
    watch(config.build.paths.style, {base: config.build.src, cwd: config.build.src}, style);
    watch(config.build.paths.script, {base: config.build.src, cwd: config.build.src}, script);
    watch(config.build.paths.pages, {base: config.build.src, cwd: config.build.src}, pages);
    
    watch([config.build.paths.images, 
    config.build.paths.fonts], {base: config.build.src, cwd: config.build.src}, bs.reload);
    watch('**', {base: config.build.public, cwd: config.build.public}, bs.reload);

    bs.init({
        notify: false,
        server: {
            baseDir: [config.build.temp, config.build.src, config.build.public],
            routes: {
                '/node_modules': 'node_modules'
            }
        }
    });
}

const compile = parallel(style, script, pages);
const build = series(clean, parallel(series(compile, useref), images, fonts, extra));
const develop = series(compile, serve);

module.exports = {
    clean,
    build,
    develop
}